package thomas.springmvc.ajax.controller;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;

import thomas.springmvc.ajax.pojo.Brand;
import thomas.springmvc.ajax.pojo.Displacement;
import thomas.springmvc.ajax.pojo.Product;
import thomas.springmvc.ajax.request.PriceRequest;

@Controller
public class CarController {
	
	private Log LOG = LogFactory.getLog(CarController.class);
	
	private Map<Integer, List<Product>> brandMap = new HashMap<Integer, List<Product>>();
	private Map<Integer, List<Displacement>> productMap = new HashMap<Integer, List<Displacement>>();
	
	@RequestMapping(value ={"", "/"}, method=RequestMethod.GET)
	public String home(Model model){
		return "home";
	}
	
	@GetMapping("/toPrice")
	public String toGetCarPrices(Model model){
		this.prepareCarBrands(model);
		PriceRequest carPriceRequest = new PriceRequest();
		model.addAttribute("carPriceRequest", carPriceRequest);
		return "priceForm";
	}
	/*
	 * @RequestBody
	 *　　1、@requestBody注解常用来处理content-type不是默认的application/x-www-form-urlcoded编码的内容，
	 *		比如说：application/json或者是application/xml等。一般情况下来说常用其来处理application/json类型。

　　2、

　　　　通过@requestBody可以将请求体中的JSON字符串绑定到相应的bean上，当然，也可以将其分别绑定到对应的字符串上。
　　　　例如说以下情况：
　　　　$.ajax({
　　　　　　　　url:"/login",
　　　　　　　　type:"POST",
　　　　　　　　data:'{"userName":"admin","pwd","admin123"}',
　　　　　　　　content-type:"application/json charset=utf-8",
　　　　　　　　success:function(data){
　　　　　　　　　　alert("request success ! ");
　　　　　　　　}
　　　　});

　　　　@requestMapping("/login")
　　　　public void login(@requestBody String userName,@requestBody String pwd){
　　　　　　System.out.println(userName+" ："+pwd);
　　　　}
　　　　这种情况是将JSON字符串中的两个变量的值分别赋予了两个字符串，但是呢假如我有一个User类，拥有如下字段：
　　　　　　String userName;
　　　　　　String pwd;
　　　　那么上述参数可以改为以下形式：@requestBody User user 这种形式会将JSON字符串中的值赋予user中对应的属性上
　　　　需要注意的是，JSON字符串中的key必须对应user中的属性名，否则是请求不过去的。
	 */
	@GetMapping("/products")
	@ResponseBody //@ResponseBody will convert the return object to json object and return to Client. 
	//
	public List<Product> getCarProducts(@RequestParam List<Integer> brands, ///products?brands=1 or /products?brands=2&brands=3
			//@RequestParam Integer brands, ///products?brands=1
			//@RequestParam User user,
			//@RequestBody User user,
										//@RequestBody PriceRequest priceRequest, 
										Model model){
		//List<Integer> brands = priceRequest.getBrands();
		//LOG.info("brands: " + user.getBrands());
		LOG.info("brands: " + brands);
		
		return new ArrayList<Product>();
	}
	
	@PostMapping("/products")
	@ResponseBody //@ResponseBody will convert the return object to json object and return to Client. 
	//@ModelAttribute("productList") //can't not add ModelAttribute, when the return is already used to @ResponseBody
	public List<Product> products(PriceRequest priceRequest, 
										Model model){
		LOG.info("brands: " + priceRequest.getBrands());	
		List<Product> productsToChose = new ArrayList<Product>();
		for(Integer brandId: priceRequest.getBrands()){
			productsToChose.addAll(this.brandMap.get(brandId));
		}
		productsToChose.forEach(LOG::info);
		//model.addAttribute("productList", productsToChose); // can't refresh the productList in F/E like this
		return productsToChose;
	}
	
	@PostMapping("/displacements")
	@ResponseBody //@ResponseBody will convert the return object to json object and return to Client. 
	public List<Displacement> displacements(PriceRequest priceRequest, 
										Model model){
		List<Displacement> displacementsToChose = new ArrayList<Displacement>();
		for(Integer productId: priceRequest.getProducts()){
			displacementsToChose.addAll(this.productMap.get(productId));
		}
		LOG.info("displacementsToChose: " + displacementsToChose);
		return displacementsToChose;
	}
	
	 
	private void prepareCarBrands(Model model){
		List<Brand>  brandList=  new ArrayList<Brand>();
		
		Brand benZ = new Brand(1, "BenZ");
		
		Product GLA = new Product(1, "GLA");
		Product GLC = new Product(2, "GLC");
		List<Product> benZProducts = new ArrayList<Product>();
		benZProducts.add(GLA);
		benZProducts.add(GLC);
		this.brandMap.put(benZ.getId(), benZProducts);		
		List<Displacement> glaDisplacement = new ArrayList<Displacement>();
		glaDisplacement.add(new Displacement(1, "1.1"));
		glaDisplacement.add(new Displacement(2, "1.2"));
		List<Displacement> glcDisplacement = new ArrayList<Displacement>();
		glcDisplacement.add(new Displacement(3, "1.3"));
		glcDisplacement.add(new Displacement(4, "1.4"));		
		this.productMap.put(GLA.getId(), glaDisplacement);
		this.productMap.put(GLC.getId(), glcDisplacement);

		
		Brand toyota = new Brand(2, "Toyota");
		
		Product CHR = new Product(3, "CHR");
		Product RAV4 = new Product(4, "RAV4");
		List<Product> toyotaProducts = new ArrayList<Product>();
		toyotaProducts.add(CHR);
		toyotaProducts.add(RAV4);
		this.brandMap.put(toyota.getId(), toyotaProducts);		
		List<Displacement> chrDisplacement = new ArrayList<Displacement>();
		chrDisplacement.add(new Displacement(5, "1.5"));
		chrDisplacement.add(new Displacement(6, "1.6"));
		List<Displacement> rav4Displacement = new ArrayList<Displacement>();
		rav4Displacement.add(new Displacement(7, "1.7"));
		rav4Displacement.add(new Displacement(8, "1.8"));		
		this.productMap.put(CHR.getId(), chrDisplacement);
		this.productMap.put(RAV4.getId(), rav4Displacement);
		
		Brand nissan = new Brand(3, "NISSAN");
		
		brandList.add(benZ);
		brandList.add(toyota);
		brandList.add(nissan);
		
		model.addAttribute("brandList", brandList);
	}
}
